From 7543fd1645dbfece52abc1157876531149a5064b Mon Sep 17 00:00:00 2001 From: "robertlipe@gmail.com" Date: Sat, 12 Nov 2011 22:47:03 +0000 Subject: [PATCH] Submit new geocache writer. I've been sitting on this for over a year. Earth 5.2 is largely forgotten now and 6.1 renders this javascript just fine. Use JQuery tabs to tab display. Only pop labels on a hover state. Reduce size of icons. Generally make KML better for geocaches. git-svn-id: http://gpsbabel.googlecode.com/svn/trunk@4106 f51c46e8-681c-474f-0cfe-069cfd0219fb --- gpsbabel/kml.c | 266 +++++++++++++++++++++++++++++--- gpsbabel/reference/earth-gc.kml | 251 ++++++++++++++++++++++++++++-- 2 files changed, 483 insertions(+), 34 deletions(-) diff --git a/gpsbabel/kml.c b/gpsbabel/kml.c index 4b9ebf67a..551d05903 100644 --- a/gpsbabel/kml.c +++ b/gpsbabel/kml.c @@ -52,6 +52,7 @@ static int trackdata; static int trackdirection; static int max_position_points; static int line_width; +static int html_encrypt; static int indent_level; @@ -442,6 +443,10 @@ kml_write_xml(int indent, const char* fmt, ...) indent_level--; } + if (indent_level < 0) { + fatal("Indention nesting problem in KML writer."); + } + if (fmt[1] != '!' && do_indentation) { for (i = 0; i < indent_level; i++) { gbfputs(" ", ofd); @@ -997,24 +1002,147 @@ static void kml_output_tailer(const route_head* header) /* * Completely different writer for geocaches. */ + +// Text that's common to all tabs. +static +void kml_gc_all_tabs_text(void) +{ + // kml_write_xml(0, " \n"); + kml_write_xml(0, "\n"); + kml_write_xml(0, "$[gc_num] $[gc_name] \n"); + kml_write_xml(0, "a $[gc_type],
on $[gc_placed] by $[gc_placer]
\n"); + kml_write_xml(0, "Difficulty: \"$[gc_diff]\"\n"); + kml_write_xml(0, " Terrain: \"$[gc_terr]\"
\n"); + kml_write_xml(0, "Size: \"$[gc_cont_icon]\"/ ($[gc_cont_icon])
\n"); + +} + +const char* map_templates[] = { + "Google Maps", + "Google Street View", + "Geocaching.com Google Map", + "MyTopo Maps", + "MapQuest", + "Bing Maps", + "Yahoo Maps", + "Rand McNally", + "MSR Maps (Formerly Terraserver)", + "Open Cycle Maps", + "Open Street Maps", + NULL +}; + + static -void kml_gc_make_ballonstyle(void) +void kml_gc_make_balloonstyletext(void) { - // BalloonStyle for Geocaches. - kml_write_xml(1, "\n"); + kml_write_xml(-1, "\n"); + + kml_write_xml(1, "
\n"); + kml_gc_all_tabs_text(); + kml_write_xml(0, "$[gc_logs]\n"); + kml_write_xml(-1, "
\n"); + + // "Extra" stuff tab. + kml_write_xml(1, "
\n"); + kml_gc_all_tabs_text(); + kml_write_xml(0, "

Extra Maps

\n"); + + const char** tp; + kml_write_xml(1, "
\n"); // fragment-3. + + kml_write_xml(0, "\n"); // tabs. + kml_write_xml(0, "\n"); + kml_write_xml(0, "\n"); + + kml_write_xml(-1, "]]>\n"); +} + +static +void kml_gc_make_balloonstyle(void) +{ + // For Normal style of gecoaches, scale of label is set to zero + // to make the label invisible. On hover (highlight?) enlarge + // the icon sightly and set the scale of the label to 1 so the + // label pops. + // It's unfortunate that we have to repeat so much of the template + // but KML doesn't have a cascading style-like substance. + // + kml_write_xml(1, "\n"); + + kml_write_xml(1, "\n"); + + kml_write_xml(1, "\n"); + + kml_write_xml(1, "\n"); + kml_write_xml(0, "normal\n"); + kml_write_xml(0, "#geocache_n\n"); + kml_write_xml(-1, "\n"); + + kml_write_xml(1, "\n"); + kml_write_xml(0, "highlight\n"); + kml_write_xml(0, "#geocache_h\n"); + kml_write_xml(-1, "\n"); + + kml_write_xml(-1, "\n"); } static @@ -1115,6 +1243,11 @@ kml_lookup_gc_container(const waypoint* waypointp) char* kml_gc_mkstar(int rating) { static char tmp[40]; + + if (rating < 0 || rating > 50 || rating % 5 != 0) { + fatal("Bogus difficulty or terrain rating."); + } + if (0 == rating % 10) { snprintf(tmp, sizeof(tmp), "stars%d", rating / 10); } else { @@ -1124,9 +1257,88 @@ char* kml_gc_mkstar(int rating) return tmp; } +// Returns an allocated buffer that must be freed. +char* kml_geocache_get_logs(const waypoint* wpt) +{ + char* r = xstrdup(""); + + fs_xml* fs_gpx = (fs_xml*)fs_chain_find(wpt->fs, FS_GPX); + if (!fs_gpx) { + return r; + } + + xml_tag* root = fs_gpx->tag; + xml_tag* curlog = NULL; + xml_tag* logpart = NULL; + curlog = xml_findfirst(root, "groundspeak:log"); + while (curlog) { + time_t logtime = 0; + struct tm* logtm = NULL; + + // Unless we have a broken GPX input, these logparts + // branches will always be taken. + logpart = xml_findfirst(curlog, "groundspeak:type"); + if (logpart) { + r = xstrappend(r, "

"); + r = xstrappend(r, logpart->cdata); + r = xstrappend(r, ""); + } + + logpart = xml_findfirst(curlog, "groundspeak:finder"); + if (logpart) { + r = xstrappend(r, " by "); + r = xstrappend(r, logpart->cdata); + // xfree( f ); + } + + logpart = xml_findfirst(curlog, "groundspeak:date"); + if (logpart) { + logtime = xml_parse_time(logpart->cdata, NULL); + logtm = localtime(&logtime); + if (logtm) { + char* temp; + xasprintf(&temp, + " %04d-%02d-%02d", + logtm->tm_year+1900, + logtm->tm_mon+1, + logtm->tm_mday); + r = xstrappend(r, temp); + xfree(temp); + } + } + + logpart = xml_findfirst(curlog, "groundspeak:text"); + if (logpart) { + char* encstr = NULL; + char* s = NULL; + char* t = NULL; + int encoded = 0; + encstr = xml_attribute(logpart, "encoded"); + encoded = (encstr[0] != 'F'); + + if (html_encrypt && encoded) { + s = rot13(logpart->cdata); + } else { + s = xstrdup(logpart->cdata); + } + + r = xstrappend(r, "
"); + t = html_entitize(s); + r = xstrappend(r, t); + xfree(t); + xfree(s); + } + + r = xstrappend(r, "

"); + curlog = xml_findnext(root, curlog, "groundspeak:log"); + } + return r; +} + static void kml_geocache_pr(const waypoint* waypointp) { char* p, *is; + char date_placed[100]; // Always long engough for a date. kml_write_xml(1, "\n"); @@ -1136,6 +1348,12 @@ static void kml_geocache_pr(const waypoint* waypointp) // Timestamp kml_output_timestamp(waypointp); + if (waypointp->creation_time) { + strftime(date_placed, sizeof(date_placed), + "%d-%b-%Y", localtime(&waypointp->creation_time)); + } else { + date_placed[0] = '\0'; + } kml_write_xml(0, "#geocache\n"); is = kml_lookup_gc_icon(waypointp); @@ -1168,6 +1386,7 @@ static void kml_geocache_pr(const waypoint* waypointp) } kml_write_xml(0, "%d\n", waypointp->gc_data->placer_id); + kml_write_xml(0, "%s\n", date_placed); kml_write_xml(0, "%s\n", kml_gc_mkstar(waypointp->gc_data->diff)); kml_write_xml(0, "%s\n", kml_gc_mkstar(waypointp->gc_data->terr)); @@ -1176,17 +1395,24 @@ static void kml_geocache_pr(const waypoint* waypointp) // Highlight any issues with the cache, such as temp unavail // or archived. - kml_write_xml(0, ""); + const char* issues = ""; if (waypointp->gc_data->is_archived == status_true) { - kml_write_xml(0, "<font color=\"red\">This cache has been archived.</font><br/>\n"); + issues = "<font color=\"red\">This cache has been archived.</font><br/>\n"; } else if (waypointp->gc_data->is_available == status_false) { - kml_write_xml(0, "<font color=\"red\">This cache is temporarily unavailable.</font><br/>\n"); + issues = "<font color=\"red\">This cache is temporarily unavailable.</font><br/>\n"; } - kml_write_xml(0, "\n"); + kml_write_xml(0, "%s\n", issues); + + kml_write_xml(0, "%f\n", waypointp->latitude); + kml_write_xml(0, "%f\n", waypointp->longitude); kml_write_xml(0, "%s\n", gs_get_cachetype(waypointp->gc_data->type)); + kml_write_xml(0, "%s\n", is); kml_write_xml(0, "\n", waypointp->gc_data->desc_short.utfstring ? waypointp->gc_data->desc_short.utfstring : ""); kml_write_xml(0, "\n", waypointp->gc_data->desc_long.utfstring ? waypointp->gc_data->desc_long.utfstring : ""); + char* logs = kml_geocache_get_logs(waypointp); + kml_write_xml(0, "\n", logs); + xfree(logs); kml_write_xml(-1, "\n"); @@ -1516,7 +1742,7 @@ static void kml_route_tlr(const route_head* header) kml_output_tailer(header); } -// For Earth 5.0, we write a LookAt that encompasses +// For Earth 5.0 and later, we write a LookAt that encompasses // the bounding box of our entire data set and set the event times // to include all our data. void kml_write_AbstractView(void) @@ -1669,7 +1895,7 @@ void kml_write(void) } if (traits->trait_geocaches) { - kml_gc_make_ballonstyle(); + kml_gc_make_balloonstyle(); } if (traits->trait_heartrate || diff --git a/gpsbabel/reference/earth-gc.kml b/gpsbabel/reference/earth-gc.kml index 52b824d7c..e51054451 100644 --- a/gpsbabel/reference/earth-gc.kml +++ b/gpsbabel/reference/earth-gc.kml @@ -39,18 +39,188 @@ #waypoint_h - + + + + + normal + #geocache_n + + + highlight + #geocache_h + + Waypoints @@ -71,11 +241,15 @@ Points géodésiques du Québec Sverdrup2 6293 + 15-Aug-2002 stars1 stars1 virtual - + + 46.133333 + -73.000000 Locationless (Reverse) Cache + http://www.geocaching.com/images/kml/8.png + Found it by Christopher R & Pooh B 2005-07-12
This marker is not in Quebec but it is a Geodesic marker in Clarenville, Newfoundland, Canada! + +Found this one while hunting a traditional cache and thought of this cache right away! + +It is located on Bare Mountain in Clarenville - There are aactually two markers within 15 feet of one another on Bare Mountain... + +Smiles Pooh Bear + +Ce marqueur n'est pas au Québec mais c'est un marqueur géodésique dans Clarenville, Terre-Neuve, Canada! + +A trouvé celui-ci tandis que chasse une cachette traditionnelle et pensé à cette cachette tout de suite! Elle est située sur la montagne nue dans Clarenville - il y a aactually deux marqueurs à moins de 15 pieds d'un des autres sur la montagne nue... Ours De Pooh De Sourires + + +

Found it by TravelBen 2005-06-26
[:D] 14h22 + +Marqueur du Service de la Géodégie (c'est bien un "g" pas un "s") du Québec. + +Position Average (100 échantillons): +N 45° 26.872 W 075° 56.410, 21 mètres d'altitude +UTM: 18T E 582877 N 5033250 + +Ce marqueur se trouve dans le ville de Senneville, sur un monument décrivant une page d'histoire du Québec, sur le bas côté avant droit. + +Près de la cache: Exo-07 La Jumelle de Loudiver (GCP3VE)

Found it by etasse 2005-06-03
MRN marker 94K4731 in Gatineau, QC. corner of Du Rhone and Gatineau Ave. + +Position Average +N 45° 29.5247 W 075° 43.0049 59.49m +UTM 18T 0443995 5037866 + +Least Squares Average +N 45° 29.5257 W 075° 43.0043 55.74m +UTM 18T 0443996 5037868 + +This pole has everything: An underground cable warning, a geodesic mark, a bus stop and a garage sale sign. + +Judging by the coordinates it looks like the coords should be 45°29'31.5" -75°43'0" I placed the GPS antenna right against the marker, to no avail. + +

Found it by Katou 2005-06-03
Un bo point géodésique a Lotbinière..en allant faire une nouvelle cache a l'île richelieu ;-) + +

Found it by Gps_Gulliver&DauphinBleu 2005-05-29
Point Geodesique situe near Port de Plaisance de Longueuil +sur le bord du fleuve st-laurent. +Il y a des sentiers et une grande piste cyclable +Enjoy !

]]>
-73.000000,46.133333 @@ -136,11 +353,15 @@ Good luck!]]> Oozy rat in a sanitary zoo robertlipe 32733 + 29-Jun-2003 stars3 stars2 not_chosen - + + 35.921667 + -86.861667 Unknown Cache + http://www.geocaching.com/images/kml/8.png Now that it's intuitively obvious to even the most casual observer where the cache is, turn on your geo-mojo and go find it.
Member of Middle Tennessee GeoCachers Club [www.mtgc.org]

]]> + Found it by littlepod 2005-07-03
Enjoyed the puzzle. We seemed to be about 50ft off though. TFTC.

Write note by robertlipe 2005-04-29
TB Drop to show he's hanging out in Nashville until we blast off for Geowoodstock in a few weeks.

Found it by Big Bumblebee 2005-04-18
Found it a while ago. Thanks.

Write note by robertlipe 2005-03-27
I had to renew my permit with the CDC and in doing so, I trolled out here verified that the infectious ooze is fully within specification and industry accepted tolerance. Ooze On!

Found it by Virtual Babe 2004-12-27
This was a great cache, however on this day I considered it a FIFM cache (Fun, Invigorating, Frustrating and Maddening), especially when the cache was not replaced in the proper spot by the previous cacher! Thanks anyway!! +

Write note by robertlipe 2004-01-12
I got a complaint from the CDC about oozy rat this weekend. I went out tonight in the dark and verified that the infectious ooze is fully within specification and industry accepted tolerance. (Although I realize now I did misstate the cache container to the reporting officer when confronted. It's, uuuuh, smaller than I said.)

Write note by robertlipe 2003-10-04
In the expectation that this cache will get some traffic in the next 48 hours, Ryan and I checked it earlier today. The Rat is Oozing just as we planned it.

Write note by robertlipe 2003-07-03
It won't earn him a smiley face, but I've confirmed that rickrich would have indeed sunk the battleship! Thanx for playing. You get a copy of the home game and some rice-a-roni...

]]>
-86.861667,35.921667 -- 2.30.2